package lx.util;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
// 1.5.5
// import org.bytedeco.opencv.global.opencv_core;
// import org.bytedeco.opencv.opencv_core.IplImage;
// 1.4.4
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @Description:
 * @Author: lixing
 * @Date: 2021/6/18 16:31
 */
public class VideoUtil {
//    public static void main(String[] args) throws Exception {
//        //System.out.println(System.getProperty("java.library.path"));
//        try {
//            //fetchFrame("C:\\Users\\lixing\\Desktop\\46.mp4", "C:\\Users\\lixing\\Desktop\\sls.png");
//            fetchFrame("https://etiger.oss-cn-hangzhou.aliyuncs.com/etiger/pTbztiHFt4Nb4ZjmGBQXN8J4eehTEPxt.mp4", "png");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param videofile 源视频文件路径
     * @throws Exception
     * @throws IOException
     */
    public static InputStream fetchFrame(String videofile, String imgType) throws Exception, IOException {
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
        ff.start();
        ff.getAudioChannels();
        String rotate = ff.getVideoMetadata("rotate");//视频的旋转角度
        int lenght = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        InputStream inputStream = null;
        while (i < lenght) {
            // 过滤前5帧，避免出现全黑的图片，依自己情况而定
            f = ff.grabFrame();
            if ((i > 5) && (f.image != null)) {
                IplImage src = null;
                if (null != rotate && rotate.length() > 1) {
                    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
                    src = converter.convert(f);
                    f = converter.convert(rotate(src, Integer.parseInt(rotate)));
                }
                inputStream = doExecuteFrame(f, imgType);
                break;
            }
            i++;
        }
        return inputStream;
    }


    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    public static InputStream doExecuteFrame(Frame f, String imgType) {
        if (null == f || null == f.image) {
            return null;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        // 图片对象
        BufferedImage bufferedImage = converter.getBufferedImage(f);
        // 字节输出流
        ByteArrayOutputStream byteArrayOutputStream = null;
        //
        ImageOutputStream imageOutputStream = null;
        // 字节输入流
        InputStream inputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            imageOutputStream = ImageIO.createImageOutputStream(byteArrayOutputStream);
            ImageIO.write(bufferedImage, imgType, imageOutputStream);
            inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            // 输出到本地测试
            //Files.copy(inputStream, Paths.get("C:\\Users\\lixing\\Desktop\\视频转图片1.png"));
            //ImageIO.write(bufferedImage, imgType, new File("C:\\Users\\lixing\\Desktop\\视频转图片2.png"));
            Files.copy(inputStream, Paths.get("/home/1.png"));
            ImageIO.write(bufferedImage, imgType, new File("/home/2.png"));
            return inputStream;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException ioe) {
                    ioe.fillInStackTrace();
                }
            }
            //
            if (imageOutputStream != null) {
                try {
                    imageOutputStream.close();
                } catch (IOException ioe) {
                    ioe.fillInStackTrace();
                }
            }
            //
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ioe) {
                    ioe.fillInStackTrace();
                }
            }
        }
        //
        return inputStream;
    }

}
